package eth

import (
	"bytes"
	"fmt"
	"gitee.com/liumou_site/logger"
	"golang.org/x/text/encoding/simplifiedchinese"
	"golang.org/x/text/transform"
	"io"
	"net"
	"os"
	"os/exec"
	"runtime"
	"strings"
)

// GetEthDNS 获取以太网的DNS配置。
// 该方法根据当前操作系统的类型调用相应的DNS获取方法。
// 参数:
//
//	eth - 以太网接口名称。
//
// 返回值:
//
//	一个net.IP切片，包含DNS服务器地址。
//	如果操作系统不支持或发生错误，则返回错误。
func (e *Eth) GetEthDNS(eth string) ([]net.IP, error) {
	// 根据不同的操作系统类型，调用相应的DNS获取方法。
	switch runtime.GOOS {
	case "windows":
		// 在Windows操作系统中，调用getWindowsDNS方法获取DNS配置。
		return e.getWindowsDNS(eth)
	case "linux", "darwin":
		// 在Linux和macOS操作系统中，调用getUnixDNS方法获取DNS配置。
		return e.getUnixDNS()
	default:
		// 如果操作系统不受支持，则返回错误。
		return nil, fmt.Errorf("unsupported OS: %s", runtime.GOOS)
	}
}

// getWindowsDNS 获取Windows系统下特定网卡的DNS服务器列表。
// 该函数通过执行ipconfig命令来获取网络配置信息，然后从中解析出DNS服务器的IP地址。
// 参数eth是网卡的名称，用于识别目标网卡。
// 返回值是一个net.IP类型的切片，包含了DNS服务器的IP地址，以及一个错误值，用于指示操作是否成功。
func (e *Eth) getWindowsDNS(eth string) ([]net.IP, error) {
	// 执行ipconfig /all命令获取网络配置信息。
	out, err := exec.Command("ipconfig", "/all").Output()
	if err != nil {
		logger.Error(err)
		return nil, fmt.Errorf("failed to execute ipconfig: %v", err)
	}
	// 将GBK编码转换为UTF-8
	decoder := simplifiedchinese.GBK.NewDecoder()
	reader := transform.NewReader(bytes.NewReader(out), decoder)
	utf8Out, err := io.ReadAll(reader)
	if err != nil {
		logger.Error(err)
		return nil, fmt.Errorf("failed to decode output: %v", err)
	}
	var dnsServers []net.IP
	lines := strings.Split(string(utf8Out), "\n")
	foundInterface := false
	for index, line := range lines {
		// 查找指定的网卡接口
		if strings.Contains(line, eth) {
			foundInterface = true
			continue
		}
		// 调试模式下记录日志
		if e.Debug {
			logger.Debug(index, line)
		}
		// 解析DNS服务器地址
		if foundInterface && strings.HasPrefix(line, "  DNS") {
			parts := strings.Fields(line)
			if len(parts) > 1 {
				ip := net.ParseIP(parts[1])
				if ip != nil {
					dnsServers = append(dnsServers, ip)
				}
			}
		}
	}
	if len(dnsServers) == 0 {
		return nil, fmt.Errorf("no DNS servers found for interface %s", eth)
	}
	return dnsServers, nil
}

// getUnixDNS 读取 Unix 系统的 DNS 服务器配置。
// 该函数从 "/etc/resolv.conf" 文件中解析 DNS 服务器的 IP 地址。
// 返回值是一个 net.IP 切片，包含所有解析出的 DNS 服务器 IP 地址，以及一个错误对象，如果读取或解析过程中发生错误，则返回相应的错误。
func (e *Eth) getUnixDNS() ([]net.IP, error) {
	// 读取 "/etc/resolv.conf" 文件内容
	out, err := os.ReadFile("/etc/resolv.conf")
	if err != nil {
		// 如果读取文件失败，返回错误
		return nil, fmt.Errorf("failed to read /etc/resolv.conf: %v", err)
	}

	// 初始化 DNS 服务器 IP 切片
	var dnsServers []net.IP
	// 将文件内容按行分割成字符串切片
	lines := strings.Split(string(out), "\n")
	// 遍历每一行，寻找以 "nameserver" 开头的行
	for _, line := range lines {
		if strings.HasPrefix(line, "nameserver") {
			// 分割行内容，获取 DNS 服务器 IP 地址
			parts := strings.Fields(line)
			if len(parts) > 1 {
				// 解析 IP 地址
				ip := net.ParseIP(parts[1])
				if ip != nil {
					// 如果 IP 地址有效，添加到 DNS 服务器 IP 切片中
					dnsServers = append(dnsServers, ip)
				}
			}
		}
	}
	// 返回所有解析出的 DNS 服务器 IP 地址
	return dnsServers, nil
}
